package repository

import (
	"GIN-API/global"
	"GIN-API/internal/models"
	"GIN-API/internal/models/DTO"
	"context"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"strconv"
	"time"
)

type ArticleRepository struct {
	db *gorm.DB
}

func NewArticleRepo(db *gorm.DB) *ArticleRepository {
	return &ArticleRepository{db: db}
}

// CreateArticle 创建文章
func (ar *ArticleRepository) CreateArticle(article *models.Article) error {
	defer ar.clearCache(article.AuthorID)
	return ar.db.Create(article).Error
}

// GetArticleByID 根据文章 ID 获取文章信息
func (ar *ArticleRepository) GetArticleByID(id uint) (*models.Article, error) {
	var article models.Article
	err := ar.db.First(&article, id).Error
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, nil
		}
		return nil, err
	}
	return &article, nil
}

// UpdateArticle 更新文章信息
func (ar *ArticleRepository) UpdateArticle(article *models.Article) (uint, error) { // 修改返回类型为 (uint, error)
	defer ar.clearCache(article.AuthorID)
	result := ar.db.Model(article).Updates(article)
	if result.Error != nil {
		return 0, result.Error
	}
	err := ar.db.First(&article, article.ID).Error
	if err != nil {
		return 0, err
	}
	return article.CoverId, nil
}

// DeleteArticle 根据文章 ID 删除文章
func (ar *ArticleRepository) DeleteArticle(id uint) (error, uint) {
	// 先查询获取作者ID
	var article models.Article
	if err := ar.db.Select("author_id", "cover_id").First(&article, id).Error; err != nil {
		return err, 0
	}

	defer ar.clearCache(article.AuthorID)
	return ar.db.Delete(&models.Article{}, id).Error, article.CoverId
}

// GetAllArticles 获取所有文章
func (ar *ArticleRepository) GetAllArticles(req *DTO.ListArticleRequest, authorID uint) ([]*models.Article, int64, error) {
	ctx := context.Background()
	cacheKey := generateCacheKey(req, authorID)

	// 1. 尝试从Redis获取缓存
	totalStr, err := global.Redis.Get(ctx, cacheKey).Result()
	if err == nil {
		total, _ := strconv.ParseInt(totalStr, 10, 64)
		articles, err := getPaginatedData(ar.db, req) // 原有分页查询逻辑
		return articles, total, err
	}

	// 2. 缓存未命中时查询数据库
	var total int64
	baseQuery := buildBaseQuery(ar.db, req)
	if err := baseQuery.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 3. 异步更新缓存（带过期时间）
	go func() {
		global.Redis.SetEX(ctx, cacheKey, total, 5*time.Minute) // 缓存5分钟
	}()

	// 4. 获取分页数据
	articles, err := getPaginatedData(baseQuery, req)
	return articles, total, err

}

// 生成缓存键（排除分页参数）
func generateCacheKey(req *DTO.ListArticleRequest, authorID uint) string {
	if req == nil {
		return fmt.Sprintf("article:total:%d", authorID)
	}
	// 关键筛选参数组合成缓存键
	return fmt.Sprintf("article:total:%d:%d:%d:%s:%s",
		authorID,
		req.Status,
		req.ChannelId,
		req.BeginPubDate,
		req.EndPubDate,
	)
}

// 在数据变更操作后清除相关缓存
func (ar *ArticleRepository) clearCache(authorID uint) {
	ctx := context.Background()
	// 使用通配符匹配所有该作者的缓存键
	pattern := fmt.Sprintf("article:total:%d:*", authorID)
	keys, _ := global.Redis.Keys(ctx, pattern).Result()
	global.Redis.Del(ctx, keys...)
}

// 原有查询逻辑拆分
func buildBaseQuery(db *gorm.DB, req *DTO.ListArticleRequest) *gorm.DB {
	query := db.Model(&models.Article{})

	// 应用筛选条件
	if req != nil {
		// 草稿状态设置
		switch req.Status {
		case 0:
			query = query.Where("draft = ?", true)
		case 1:
			query = query.Where("draft = ?", false)
		}

		// 频道筛选
		if req.ChannelId > 0 {
			query = query.Where("channel_id = ?", req.ChannelId)
		}

		// 时间范围筛选
		if req.BeginPubDate != "" && req.EndPubDate != "" {
			query = query.Where("updated_at BETWEEN ? AND ?",
				req.BeginPubDate, req.EndPubDate)
		} else if req.BeginPubDate != "" {
			query = query.Where("updated_at >= ?", req.BeginPubDate)
		} else if req.EndPubDate != "" {
			query = query.Where("updated_at <= ?", req.EndPubDate)
		}
	}
	return query
}

func getPaginatedData(query *gorm.DB, req *DTO.ListArticleRequest) ([]*models.Article, error) {
	// 应用分页逻辑（同原有逻辑）
	// 分页处理
	if req.PageSize > 0 {
		offset := (req.Page - 1) * req.PageSize
		query = query.Limit(req.PageSize).Offset(offset)
	}
	var articles []*models.Article
	if err := query.Find(&articles).Error; err != nil {
		return nil, err
	}
	return articles, nil
}
